package com.net.xpay.partner.secutiry;

import com.google.common.base.Strings;
import com.net.xpay.common.domain.partner.Partner;
import com.net.xpay.common.enums.user.LoginMethod;
import com.net.xpay.common.manager.partner.PartnerManager;
import com.net.xpay.core.constant.PoseidonErrorCode;
import org.mindrot.jbcrypt.BCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;



/**
 * @author  on 01/02/2018.
 */
@Component
public class FormLoginAuthenticationProvider implements AuthenticationProvider {
    private static final Logger LOGGER = LoggerFactory.getLogger(FormLoginAuthenticationProvider.class);
    @Autowired
    private PartnerManager partnerManager;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        FormLoginToken token = (FormLoginToken) authentication;
        if (Strings.isNullOrEmpty(token.getMobile())) {
            throw new WebAuthenticationException(PoseidonErrorCode.MOBILE_ERROR, "手机号格式不正确");
        } else if (token.getClientFrom() == null) {
            throw new WebAuthenticationException(PoseidonErrorCode.BUSINESS_ERROR, " 登陆来源错误");
        }

        try {
            return doAuthentication(token);
        } catch (AuthenticationException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.warn("partner authenticated failed|mobile={}|password={}|checkCode={}",
                    token.getMobile(), token.getPassword(), token.getCheckCode(), e);
            throw new WebAuthenticationException(PoseidonErrorCode.BUSINESS_ERROR, "登陆服务暂时不可用,请稍后重试");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return FormLoginToken.class.isAssignableFrom(authentication);
    }

    private Authentication doAuthentication(FormLoginToken token) throws AuthenticationException {
        Partner partner = partnerManager.findByMobile(token.getMobile());
        if (partner == null && token.getLoginMethod() != LoginMethod.CHECK_CODE) {
            throw new WebAuthenticationException(PoseidonErrorCode.MOBILE_NOT_FOUND, "手机号没找到");
        }

        verifyCredential(token, partner);

        if (partner == null) {
            throw new WebAuthenticationException(PoseidonErrorCode.MOBILE_NOT_FOUND, "手机号没找到");
        }

        return new Operator(partner, token);
    }

    private void verifyCredential(FormLoginToken token, Partner partner) throws AuthenticationException {
        switch (token.getLoginMethod()) {
            case PASSWORD:
                verifyPassword(token, partner);
                break;
            default:
                throw new WebAuthenticationException(PoseidonErrorCode.BUSINESS_ERROR, "登陆方式不正确,请稍后重试");
        }
    }

    private void verifyPassword(FormLoginToken token, Partner partner) throws AuthenticationException {
        String password = token.getPassword() == null ? "" : token.getPassword();
        if (!BCrypt.checkpw(password, partner.getPassword())) {
            throw new WebAuthenticationException(PoseidonErrorCode.PASSWORD_ERROR, "密码不正确");
        }
    }
}